# Adoption represents a responsibility relationship between users and issues.
# If a user "adopts" an issue, then they can update the status of the issue
# (NOT change the original issue) when the issue is addressed, presumably by
# the user.
class Adoption < ActiveRecord::Base
  belongs_to :user, :counter_cache => :adopted_issues_count
  belongs_to :issue, :counter_cache => :owners_count
  belongs_to :assigned_by, :class_name => 'User', :foreign_key => :assigned_by_id

  named_scope :recently_assigned,
                :conditions => [
                    'created_at > ?',
                    Time.now - 7.days
                  ],
                :order => 'created_at ASC'

  # a user can only adopt an issue once
  validates_uniqueness_of :user_id, :scope => :issue_id

  # returns all of the adoptions for a particular user
  def self.find_by_user( user )
    find( :all, :conditions => ['user_id = ?', user.id] )
  end

  def self.find_by_issue( issue )
    find( :all, :conditions => ['issue_id = ?', issue.id] )
  end

  # creates an adoption for issue, user
  def self.adopt( issue, user )
    if a = find( :first, :conditions =>
        ['user_id = ? AND issue_id = ?', user.id, issue.id] )
      a
    else
      create( :issue => issue, :user => user )
    end
  end

  # creates an adoption _and_ sets the "assigned_by" user
  def self.assign( issue, assignee, user )
    a = adopt( issue, assignee )
    a.update_attribute( :assigned_by_id, user.id )
    a
  end

  # removes an adoption between issue and user
  def self.disown( issue, user ) # :yields: assigned_by
    a = Adoption.find( :first, :conditions =>
        ['user_id = ? AND issue_id = ?', user.id, issue.id] )
    if a
      yield a.assigned_by if a.assigned_by and block_given?
      a.destroy
    else
      true
    end
  end

  # returns whether or not an issue is adopted/assigned
  def self.owned?( issue, user )
    a = Adoption.find( :first, :conditions =>
        ['user_id = ? AND issue_id = ?', user, issue] )
    ( !a.nil? )
  end

  def inspect
    ( !assigned_by ?
      "Adoption( #{issue.project.name} ##{issue.local_id}, #{user.display} )" :
      "Assignment( #{issue.project.name} ##{issue.local_id}, #{user.display}" +
      " ) by #{assigned_by.display}" )
  end
end
